#include "MyServer.h"
#include "MyTools.h"
#include <algorithm>
#include <windows.h>

const unsigned int kMinimumPacketSize = 2;
const unsigned int kMaxConnection = 1000;
const unsigned int kPollTime = 50;

MyServer::MyServer():mListening(false),mHost(0),mPort(0)
{
    enet_initialize();

}

MyServer::~MyServer()
{
    StopListen();
    enet_deinitialize();
}

void MyServer::Run()
{
    // any class method called in Run must be mutexed
    MYLOG("Start server..");

    mAddress.host = ENET_HOST_ANY; // localhost
    mAddress.port = mPort;

    mHost = enet_host_create(
            &mAddress,      // the address to bind the server host to
            kMaxConnection, // allowed connections
            0,  // unlimited channel count
            0); // assume any amount of outgoing bandwidth

    if( mHost == 0 )
    {
        MYLOG("Server failed to start");
        mListening=false;
        OnReadyToListen(false);
        return;
    }

    OnReadyToListen(true);

    MYLOG("Listening..");
    while(mListening)
    {
        ENetEvent event;
        while (enet_host_service(mHost, &event, kPollTime) > 0)
        {
            switch (event.type)
            {
                case ENET_EVENT_TYPE_CONNECT:
                {
                    MyConnectedClient *client = new MyConnectedClient(event.peer);
                    Lock();
                    mConnectedClients.push_back(client);
                    Unlock();
                    event.peer->data = (void *)client;
                    OnClientConnect(client);
                    break;
                }
                case ENET_EVENT_TYPE_RECEIVE:
                {
                    MyConnectedClient *client =
                        static_cast<MyConnectedClient*>(event.peer->data);

                    if (event.packet->dataLength >= kMinimumPacketSize)
                    {
                        MyMsgIn msg((char *)event.packet->data,
                            event.packet->dataLength);
                        OnReceiveMessage(client, msg);
                    }

                    enet_packet_destroy(event.packet);
                    break;
                }
                case ENET_EVENT_TYPE_DISCONNECT:
                {
                    MyConnectedClient *client =
                        static_cast<MyConnectedClient*>(event.peer->data);

                    OnClientDisconnect(client);

                    Lock();
                    mConnectedClients.erase(std::find(mConnectedClients.begin(),
                        mConnectedClients.end(),
                        client));
                    Unlock();
                    delete client;
                    event.peer->data = NULL;
                    break;
                }
                default: break;
            }
        }

        //MYLOG("Listening..");
    }
    MYLOG("Listening stop..");
}

void MyServer::ListenTo(const unsigned int &port)
{
    if(mListening) return;
    mListening=true;
    mPort=port;
    MyThread::Start();
}

void MyServer::StopListen()
{
    if(!mListening) return;
    mListening=false;
    MyThread::Join();
}

bool MyServer::IsListening()
{
    return mListening;
}
